package com.moonshineproject.plugin.haxe.haxecompiler
{
	import __AS3__.vec.Vector;
	
	import com.moonshineproject.editor.BasicTextEditor;
	import com.moonshineproject.plugin.IMenuPlugin;
	import com.moonshineproject.plugin.PluginBase;
	import com.moonshineproject.plugin.core.compiler.CompilerEventBase;
	import com.moonshineproject.plugin.core.ponycompletion.PonyCompletionEventBase;
	import com.moonshineproject.plugin.haxe.haxecompiler.commands.HaxeAutoCompleteCommand;
	import com.moonshineproject.plugin.haxe.haxecompiler.commands.HaxeCompileCommand;
	import com.moonshineproject.plugin.haxe.haxeproject.vo.HaXeProjectVO;
	import com.moonshineproject.plugin.menu.vo.MenuItem;
	import com.moonshineproject.plugin.settings.ISettingsProvider;
	import com.moonshineproject.plugin.settings.vo.ISetting;
	import com.moonshineproject.plugin.settings.vo.PathSetting;
	
	import flash.desktop.NativeProcess;
	import flash.events.Event;
	import flash.filesystem.File;
	import flash.ui.Keyboard;

	public class HaxeCompilerPlugin extends PluginBase implements IMenuPlugin, ISettingsProvider
	{
		override public function get name():String			{ return "HaXe Compiler Plugin"; }
		override public function get author():String		{ return "Moonshine Project Team"; }
		override public function get description():String	{ return "Provides compilation & autocompletion for HaXe projects."; }
		
		public var compilerPath:String;
		public function get compiler():File
		{
			return new File(compilerPath);
		}
		protected var customProcess:NativeProcess;
		
		override public function activate():void 
		{
			super.activate();
			
			dispatcher.addEventListener(CompilerEventBase.BUILD, handleCompile);
			dispatcher.addEventListener(PonyCompletionEventBase.EVENT_PONYCOMPLETE, handleAutoComplete);
		}
		
		override public function deactivate():void 
		{
			super.deactivate();
			
			dispatcher.removeEventListener(CompilerEventBase.BUILD, handleCompile);
			dispatcher.removeEventListener(PonyCompletionEventBase.EVENT_PONYCOMPLETE, handleAutoComplete);
		}
		
		public function getMenu():MenuItem
		{
			return new MenuItem(
					"HaXe", 
					[
						new MenuItem("Build", null, CompilerEventBase.BUILD,
							 'b', [Keyboard.COMMAND],
							 'b', [Keyboard.CONTROL]),
						new MenuItem("Ponycomplete", null, PonyCompletionEventBase.EVENT_PONYCOMPLETE,
							' ', [Keyboard.COMMAND],
							' ', [Keyboard.CONTROL])
					]
			);
		}
		
		public function getSettingsList():Vector.<ISetting>
		{
			return Vector.<ISetting>([
				new PathSetting(this,'compilerPath', 'Compiler', false)
			])
		}
		
		protected function handleCompile(event:Event):void
		{
			if (model.activeProject is HaXeProjectVO) 
			{
				compile(model.activeProject as HaXeProjectVO);
			}	
		}
		
		protected function compile(p:HaXeProjectVO):void
		{
			if (compilerPath == null || compilerPath == "")
			{
				error("No compiler path set, please check settings.");
				return;
			}
			
			var compileCommand:HaxeCompileCommand = new HaxeCompileCommand(compiler);
			compileCommand.compile(p, getCompilerArguments(p));
		}
		
		protected function handleAutoComplete(event:Event):void
		{
			if (model.activeProject is HaXeProjectVO
				&& model.activeEditor is BasicTextEditor) 
			{
				var p:HaXeProjectVO = model.activeProject as HaXeProjectVO;
				var file:File = BasicTextEditor(model.activeEditor).currentFile;
				
				// Only autocomplete for haxe files
				if (file.extension != "hx") return;
					
				var charIdx:int = BasicTextEditor(model.activeEditor).getEditorComponent().getCaretIndex();
				
				// Need to save before we can autocomplete
				model.activeEditor.save();
				
				autoComplete(p, file, charIdx);
			}
		}
		
		protected function autoComplete(p:HaXeProjectVO, file:File, charIdx:int):void
		{
			var path:String = p.folder.getRelativePath(file, false);
			
			var completeCommand:HaxeAutoCompleteCommand = new HaxeAutoCompleteCommand(compiler);
			completeCommand.addEventListener(Event.COMPLETE, autoCompleteDone);
			completeCommand.addEventListener(Event.CANCEL, autoCompleteCancel);
			completeCommand.complete(p, getCompilerArguments(p), path, charIdx);
		}
		
		protected function autoCompleteDone(event:Event):void
		{
			var command:HaxeAutoCompleteCommand = HaxeAutoCompleteCommand(event.target);
			
			// Show completions
			BasicTextEditor(model.activeEditor).getEditorComponent().showCompletion(command.result);
			
			// Cleanup
			autoCompleteCancel(event);
		}
		
		protected function autoCompleteCancel(event:Event):void
		{
			var command:HaxeAutoCompleteCommand = HaxeAutoCompleteCommand(event.target);
			command.removeEventListener(Event.COMPLETE, autoCompleteDone);
			command.removeEventListener(Event.CANCEL, autoCompleteCancel);
		}
		
		protected function getCompilerArguments(p:HaXeProjectVO):Vector.<String>
		{
			var args:Vector.<String> = new Vector.<String>();
			
			// TODO: Add options here
			var outputFile:String = p.folder.getRelativePath(p.swfOutput.path);
			
			args.push("-swf9");
			args.push(outputFile);
			args.push("-main");
			args.push(p.buildOptions.mainClass);

			// Add class paths
			for each (var cp:File in p.classpaths)
			{
				// Relative if possible, else full path
				var path:String = p.folder.getRelativePath(cp);
				if (!path) path = cp.nativePath;
				
				args.push("-cp");
				args.push(path);
			}
			
			return args;
		}
		
	}
}